#!/usr/bin/env python
import os
import subprocess
import time
import datetime
import filecmp

class ThreadTest:
    def __init__(self, config, logger):
        self.config = config
        self.end_time = None
        self.logger = logger
        self.results_dir = None
        self.start_time = None



    def gnuplot(self, results, dataset, threads):

        cmd3 = """gnuplot -e "set datafile separator ' '; """
        cmd3 += "set autoscale; "
        cmd3 += "set term png large; "

        if dataset != "consolidated":
            output = self.results_dir + "/graphs/%s_threads/%s_comparison.png" % (threads, dataset)
            cmd3 += "set output '%s'; " % output
            cmd3 += "plot "
            for result in results:
                print result
                cmd3 += ''''<(grep "avg" %s)' using 5 title '%s' with lp, ''' % (result, result.split('/')[-1][:-4])
            cmd3 = cmd3[:-2] + '''"'''
            print cmd3
            subprocess.Popen(cmd3, shell=True)
        else:
            output = self.results_dir + "/%s_threads/%s_comparison.png" % (threads, dataset)
            cmd3 += "set output '%s'; " % output
            cmd3 += "plot "
            for keys, values in results.items():
                title = values[1].split('/')[-1][:-4]
                cmd3 += ''''<(grep "avg" %s)' using 5 title '%s' with lp, ''' % (values[1], title)
            cmd3 = cmd3[:-2] + '''"'''
            subprocess.Popen(cmd3, shell=True)


    def graphSingleCore(self):
        pass

    def createTraceList(self):
        filelist = "/root/qa_automation/data/performance/full_repo/full_repo.txt"
        with open(filelist, 'w') as outfile:
            cmd = "find /dev/shm/Traces -name '*cap'"
            p = subprocess.Popen(cmd, stdout = outfile, stderr = subprocess.PIPE)
            p.wait()


    def runThreadtest(self, build, dataset, filelist, iter, threads):

        if threads == 1:
            self.results_dir += "single_core/"
        else:
            self.results_dir += "%sthreads/" % threads
        if not os.path.exists(self.results_dir):
            os.makedirs(self.results_dir)

        libdir = build + "/lib"
        environ = os.environ
        environ["LD_LIBRARY_PATH"] = libdir

        log_path = "%s_%s_%sthreads.txt" % (build.split('/')[-1], dataset, str(threads))
        logfile = open(log_path, "w")

        cmd = "./threadtest -t 1 -T %s -i %s -f %s" % (threads, str(iter), filelist)
        print "\n" + cmd + "\n\n"
        threadtest_dir = build + "/threadtest"
        print mydir
        p = subprocess.Popen(cmd, cwd = threadtest_dir, env=environ, shell=True, stdout=logfile, stderr=logfile)
        p.communicate()
        return log_path


    def _setupEnvironment(self):
        # open results dir
        self.results_dir = os.path.join(self.config['results_dir'], 'threadtest')
        graphs_dir = os.path.join(self.results_dir + "graphs")
        if not os.path.exists(self.results_dir):
            os.makedirs(self.results_dir)
        if not os.path.exists(graphs_dir):
            os.makedirs(graphs_dir)


    def _patchAndMake(self, build):
        # this will have to be modified when running on our test machines
        path = os.path.join(build, "threadtest")
        patch_threadtest = "patch -b -R " + path + "/threadtest.cpp /root/builds/threadtest.patch"
        patch_makefile = "patch -b -R " + path + "/Makefile /root/builds/make.patch"
        make = "make -C " + path

        subprocess.call(patch_threadtest, shell=True)
        subprocess.call(patch_makefile, shell=True)
        subprocess.call(make, shell=True)

    def run(self):
        a_build_test = 'a_build' in self.config and self.config['a_build']
        b_build_test = 'b_build' in self.config and self.config['b_build']
        self.start_time = time.time()
        self.logger.info('Running Thread Test')
        self._setupEnvironment()
        self._patchAndMake(self.config['a_build'][:-7])
        self._patchAndMake(self.config['b_build'][:-7])


        filelists_12t = {
#                            "s11fa2" : "/root/qa_automation/data/performance/s11fa2/fl-parts.txt",
#                            "e916" : "/root/qa_automation/data/performance/e916/fl-parts.txt",
#                            "e918" : "/root/qa_automation/data/performance/e918/fl-parts.txt",
#                            "ab_crtm" : "/root/qa_automation/data/performance/ab_crtm_230k/fl-parts.txt",
#                            "ab" : "/root/qa_automation/data/performance/ab/fl-parts.txt"
                             "tester" : "/root/builds/list.txt"
                        }

        filelists_20t = {
                            "s11fa2" : "/root/qa_automation/data/performance/s11fa2/fl-parts.txt",
                            "e916" : "/root/qa_automation/data/performance/e916/fl-parts.txt",
                            "ab" : "/root/qa_automation/data/performance/ab/fl-parts.txt"
                        }

        filelists_1t = {
                            "e91618" : "/captures_dir/e91618/e91618.txt",
                            "full_repo" : "/captures_dir/full_repo/full_repo-concat.txt"
        }

        threads = [12, 20, 1]

        # Runs threadtest for 2 builds and compares the results
        if a_build_test and b_build_test:
            '''
            results_dict = {}
            for key, value in filelists_12t.items():
                a_build = self.runThreadtest(self.config['a_build'][:-7], key, value, 3, 12)
                b_build = self.runThreadtest(self.config['b_build'][:-7], key, value, 3, 12)
                results_dict[key] = [a_build, b_build]
                self.gnuplot(results_dict[key], key, 12)
            self.gnuplot(results_dict, "consolidated", 12)

            results_dict.clear()
            for key, value in filelists_20t.items():
                a_build = self.runThreadtest(self.config['a_build'][:-7], key, value, 3, 20)
                b_build = self.runThreadtest(self.config['b_build'][:-7], key, value, 3, 20)
                results_dict[key] = [a_build, b_build]
                self.gnuplot(results_dict[key], key, 20)
            self.gnuplot(results_dict, "consolidated", 20)

            results_dict.clear()
            for key, value in filelists_1t.items():
                a_build = self.runThreadtest(self.config['a_build'][:-7], key, value, 3, 1)
                b_build = self.runThreadtest(self.config['b_build'][:-7], key, value, 3, 1)
                results_dict[key] = [a_build, b_build]
                self.gnuplot(results_dict[key], key, 1)
            self.gnuplot(results_dict, "consolidated", 1)
            '''

            # Can potentially replace above 3 for loops with this
            for thread in threads:
                for key, value in "filelists_%s.items()" % thread:
                    a_build = self.runThreadtest(self.config['a_build'][:-7], key, value, 3, thread)
                    b_build = self.runThreadtest(self.config['b_build'][:-7], key, value, 3, thread)
                    results_dict[key] = [a_build, b_build]
                    self.gnuplot(results_dict[key], key, thread)
                self.gnuplot(results_dict, "consolidated", thread)
                results_dict.clear()


        e = 0
#        if a_build_test:
#            e += self.runThreadtest(3, self.config['a_build'][:-7])


        self.end_time = time.time()
        run_time = self.end_time - self.start_time
        self.logger.info('Complete in %f, exit status %s' % (run_time, e))
        return e

    '''
        # Run 20 thread datasets on 2 builds
        for key, value in filelists_20t.items():
            if a_build_test and a_build_test:
                a_build = self.matt_run(self.config['a_build'], key, value, 3, 20)
                b_build = self.matt_run(self.config['b_build'], key, value, 3, 20)
                results_dict[key] = [a_build, b_build]
                #self.gnuplot(results_dict[key], key, 20)
                print "A BUILD = " + a_build
                print "B BUILD = " + b_build
                print "\n\n"
        self.gnuplot(results_dict, 'consolidated')
    '''




    '''
        e = 0
        if a_build_test:
            e += self._runThreadTests('a_build')
        if b_build_test:
            e += self._runThreadTests('b_build')
        if a_build_test and b_build_test:
            self._compareResults_sc()
            self._compareResults_12t()
            self._compareResults_20t()
    '''
